package skipass;

import java.util.Calendar;

import skipass.container.Card;
import skipass.container.CountCard;
import skipass.container.DayCard;
import skipass.container.TimeCard;

import mycollections.MyHashMap;


public class CardStatSystem {

	MyHashMap<Integer, Boolean> cards = new MyHashMap<>();
	MyHashMap<CardType,Integer> acceptStat = new MyHashMap<>();
	MyHashMap<CardType,Integer> declineStat = new MyHashMap<>();	
	private static final int openHour = 9;
	private static final int closeHour = 17;
	private static final boolean BLOCKED = true;
	private static final boolean NOT_BLOCKED = false;
	private int lastId; 
	
	public CardStatSystem() {
		for(CardType type : CardType.values()) {
			acceptStat.put(type, 0);
			declineStat.put(type, 0);
		}
	}
	
	public Calendar getCurrentTime() {
		return Calendar.getInstance();
	}
	
	boolean isOpen() {
		int curHour = getCurrentTime().get(Calendar.HOUR_OF_DAY);
		if(curHour >= openHour && curHour < closeHour)
			return true;
		else return false;
	}
	
	public void writeStat(CardType type, boolean isAccepted) {		
		if(isAccepted) {
			acceptStat.put(type, acceptStat.get(type) + 1);
		} else {			
			declineStat.put(type, acceptStat.get(type) + 1);
		}
	}
	
	//Refactor using factory pattern?
	public Card createCard(CardType type) {
		cards.put(++lastId, false);
		switch(type) {
		case DAY:
		case DAYW:
			return new DayCard(lastId, type, 1);
		case TWODAY:
		case TWODAYW:
			return new DayCard(lastId, type, 2);
		case FIVEDAY:
			return new DayCard(lastId, type, 5);
		case SEASON:
			return new DayCard(lastId, type, 90);
		case PASS10:
		case PASS10W:
			return new CountCard(lastId, type, 10);
		case PASS20:
		case PASS20W:
			return new CountCard(lastId, type, 20);
		case PASS50:
		case PASS50W:
			return new CountCard(lastId, type, 50);
		case PASS100:
		case PASS100W:
			return new CountCard(lastId, type, 100);
		case FIRSTHALFDAY:
		case FIRSTHALFDAYW:
			return createTimeCard(type, 9, 4);
		case SECONDHALFDAY:
		case SECONDHALFDAYW:
			return createTimeCard(type, 13, 4);
		default:
			throw new IllegalArgumentException();
		}			
	}
	
	public boolean cardExists(int id) {
		if(cards.containsKey(id))
			return true;
		else return false;
	}
	
	public boolean isBlocked(int id) {
		if(cards.containsKey(id)) {
			if(cards.get(id) == NOT_BLOCKED)
				return false;
			else return true;
		}
		else throw new IllegalArgumentException();
	}
	
	public Double getAvgPassPerc() {
		int total = 0;
		int passed = 0;
		for(CardType type : CardType.values()) {
			total += (acceptStat.get(type) + declineStat.get(type));
			passed += acceptStat.get(type);									
		}
		double perc = (double) passed*100/total;
		perc = (double)Math.round(perc * 100) / 100;
		return perc;
	}
	
	public MyHashMap<CardType,Double> getPassPercGroupByCardType() {
		MyHashMap<CardType,Double> res = new MyHashMap<>();
		for(CardType type : CardType.values()) {
			int total = acceptStat.get(type) + declineStat.get(type);
			int passed = acceptStat.get(type);
			double perc = 0d;
			if(total > 0) 
				perc = (double) passed*100/total;
			perc = (double)Math.round(perc * 100) / 100;
			res.put(type, perc);
		}
		return res;
	}
	
	public void banCard(int id) {
		if(cards.containsKey(id))
			cards.put(id, BLOCKED);
		else throw new IllegalArgumentException();
	}
	
	private TimeCard createTimeCard(CardType type, int startHour, int hoursAmount) {
		Calendar startDate = Calendar.getInstance();
		startDate.set(Calendar.HOUR_OF_DAY, startHour);
		startDate.set(Calendar.MINUTE, 0);
		startDate.set(Calendar.SECOND, 0);
		Calendar endDate = (Calendar) startDate.clone();
		endDate.add(Calendar.HOUR, hoursAmount);	
		return new TimeCard(lastId, type, 1, startDate, endDate);
	}
	
}